<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */

namespace App\Services;

use Exception;
use Firebase\JWT\BeforeValidException;
use Firebase\JWT\ExpiredException;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use Firebase\JWT\SignatureInvalidException;
use UnexpectedValueException;

class JwtTokenService
{
    public const SECRET = 'VliwSuvne'; // 密钥

    /**
     * @param mixed $exp
     * @param mixed $domain
     * @return string
     */
    public function createToken(int $id, string $source, $exp, array $params, $domain)
    {
        $time = time();
        $params += [
            'iss' => $domain, // 签发者
            'aud' => $domain,
            'iat' => $time, // 签发时间
            'nbf' => $time,
            'exp' => $exp, // 过期时间
            'id' => $id,
            'source' => $source,
            'domain' => $domain,
        ];
        // $params['jti'] = [$id, $type];
        // $token = JWT::encode($params, self::SECRET,'HS256');
        // $params['token'] = $token;
        // $params['out'] = $exp - time();
        // return $params;
        return JWT::encode($params, self::SECRET, 'HS256');
    }

    /**
     * @return array
     * @throws SignatureInvalidException Provided JWT was invalid because the signature verification failed
     * @throws BeforeValidException Provided JWT is trying to be used before it's eligible as defined by 'nbf'
     * @throws BeforeValidException Provided JWT is trying to be used before it's been created as defined by 'iat'
     * @throws ExpiredException Provided JWT has since expired, as defined by the 'exp' claim
     * @throws UnexpectedValueException Provided JWT was invalid
     */
    public function parseToken(string $token)
    {
        return (array) JWT::decode($token, new Key(self::SECRET, 'HS256'));
    }

    public function verifyToken(string $token)
    {
        $payload = $this->parseToken($token);

        // 签发时间大于当前服务器时间验证失败
        if (isset($payload['iat']) && $payload['iat'] > time()) {
            return false;
        }

        // 过期时间小宇当前服务器时间验证失败
        if (isset($payload['exp']) && $payload['exp'] < time()) {
            return false;
        }

        // 该nbf时间之前不接收处理该Token
        if (isset($payload['nbf']) && $payload['nbf'] > time()) {
            return false;
        }

        return $payload;
    }

}
